//
//  randomtestadventurer.c
//  Dominion
//
//  Eric Hook
//  hooke@onid.orst.edu
//  CS362 Winter 2014
//
/////////////// randtestcard.c tests functionality of adventurer //////////////////////////////////////////////
//      adventurer (cost 6) (A) Reveal cards until 2 treasure cards revealed, put in deck, discard revealed
//      If no/only 1 treasure found, stop when full deck seen
//      Reveal cards from your deck until you reveal 2 treasure cards. Put those tresure cards in your hand and discard other revealed cards.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//      Assert: if deck comtains 2+ Treasure cards, # Treasure cards in hand + 2,
//          # Treasure cards in deck - 2,
//          hands between 0 and 2nd treasure cards to discard pile
//      Assert: if deck comtains 1 Treasure card, # Treasure cards in hand + 1,
//          # Treasure cards in deck - 1,
//          hands between 0 and 1st (only) treasure cards to discard pile
//      Assert: if deck comtains 0 Treasure card, Cards "revealed" but all revealed placed in discard (for future reshuffling when new hand created)
//      Assert: Number of actions - 1
//      Assert:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include "math.h"
#include <time.h>
#include <stdlib.h>

void setUpAdventurerPurse();
void testAdventurerCard (int playerTurn, struct gameState *G);
int getTreasureDeckCount  (struct gameState *G, int player);
int getTreasureHandCount (struct gameState *G, int player);
int compareTreasureDeckCounts (struct gameState *Gpost, struct gameState *Gpre);
int compareCoins (struct gameState *Gpost, struct gameState *Gpre);
int makeRandomHand (int player, int numCards);
int compareNumActions ( struct gameState *Gpost, struct gameState *Gpre );
int makeRandomDeck (int player, int numCards);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

int seed = 1000;
static int TEXT_FEEDBACK = 0;
int defaultKingdomCards[10] = {adventurer, council_room, feast, gardens, mine,remodel, smithy, village, baron, great_hall}; //Default cards, as defined in playDom
int treasureCards[4] = {copper, silver, gold};
struct gameState *G;
struct gameState *Gpost;
struct gameState *Gpre;

#define NUM_TESTS 100
#define NUM_UNIQUE_CARDS 30

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct gameState gameStateRandomizer () {
    int i, numPlayers ;
    G     = malloc(sizeof(struct gameState));
    Gpost = malloc(sizeof(struct gameState));
    Gpre  = malloc(sizeof(struct gameState));
    
    //srand((int)time(NULL));//time doesn't update fast enough - need fix
    srand(seed);
    memset(G, 0, sizeof(struct gameState));             // clear the game state
    initializeGame(2, defaultKingdomCards, seed, G);
    
    // Set up random gamestate//////////////
    G->numPlayers = rand() % 3 + 2;                     //random reasonable (allowed) num players 2-4
    numPlayers = G->numPlayers;
    for (i = 0; i < numPlayers; i++){
        G->deckCount[i]    = rand() % MAX_DECK;         //random reasonable num deckCount
        G->discardCount[i] = rand() % MAX_DECK;         //random reasonable num discardCount
        if (rand()% 10 < 1){
            G->handCount[i] = rand() % MAX_HAND;        //random up to very large num handCount
        }
        else {
            G->handCount[i]    = rand() % 10;           //OR a random common size handCount
        }
        
    }
    G->playedCardCount = rand() % MAX_DECK;
    G->whoseTurn = rand() % numPlayers;
    G->coins = 0;
    for (int i = 0; i < G->numPlayers; i++){
        makeRandomHand(i, G->handCount[i]);                          // make random card hand for each player
        makeRandomDeck(i, G->deckCount[i]);
    }

    return *G;
}

void setUpRandomizerAdventurer(){
    
    for (int i = 1; i < NUM_TESTS; i++) {
        seed +=1;  // seeding with time not fast enough
        gameStateRandomizer();  // make a brand new game state
        memcpy (Gpost, G, sizeof(struct gameState));
        memcpy (Gpre, G, sizeof(struct gameState));
        testAdventurerCard(Gpost->whoseTurn, Gpost);
        //compareCopperCounts(Gpost, Gpre);;
        //compareCoins(Gpost, Gpre);
        //printf("**** ERROR numActions should decrease by one when played");
        //assert (compareNumActions ( Gpost, Gpre ) == 1);  // numActions should decrease by one when card played

    }
    printf ("ALL TESTS OK - well not really. The asserts were commented out temporarily.\n");
}

void testAdventurerCard (int playerTurn, struct gameState *Gpost) {
    if (DEBUG) printf("PRE Player %i TreasureDeckCount count is: %i. TreasureHandCount count is: %i. Cards in deck: %i. DiscardCount: **%i\n", Gpre->whoseTurn, getTreasureDeckCount(Gpre, Gpre->whoseTurn), getTreasureHandCount(Gpre, Gpre->whoseTurn), Gpre->deckCount[playerTurn], Gpre->discardCount[playerTurn]);
    
    cardEffect(adventurer, 0, 0, 0, Gpost, 2, 0);  // call card effect for adventurer with new random game state
    
    if (DEBUG) printf("POST Player %i TreasureDeckCount count is: %i. TreasureHandCount count is: %i. Cards in deck: %i DiscardCount: **%i\n", Gpost->whoseTurn, getTreasureDeckCount(Gpost, Gpost->whoseTurn), getTreasureHandCount(Gpost, Gpost->whoseTurn), Gpost->deckCount[playerTurn], Gpost->discardCount[playerTurn]);

    compareTreasureDeckCounts (Gpost, Gpre); // **** POSSIBLE BUG >> if more than 2 treasure cards in deck, player should move 2 treasure cards from deck to hand. deckCount DOES decrement, but the prior values still in array. POSSIBLE bug depending upon interaction with other cards.
    
    
    printf ("!!!FINISH ADVENTURER CARD EFFECT: int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) : randomtestadventurer.c.\n\n");
}

int getTreasureDeckCount (struct gameState *G, int player){   // check to see how many Treasure cards in deck
    int TreasureCount = 0;
    for (int j = 0; j < G->deckCount[player]; j++) {
        if ( (G->deck[player][j] == (copper)) || (G->deck[player][j] == (silver)) || (G->deck[player][j] == (gold)) ) {
            TreasureCount++;
        }
    }
    if (TEXT_FEEDBACK) printf("Player %i getTreasureDeckCount() count is: %i. Cards in deck: %i \n", player, TreasureCount, G->deckCount[player]);
    return TreasureCount;
}

int getTreasureHandCount (struct gameState *G, int player){   // check to see how many Treasure cards in deck
    int TreasureCount = 0;
    for (int j = 0; j < G->handCount[player]; j++) {
        if ( (G->hand[player][j] == (copper)) || (G->hand[player][j] == (silver)) || (G->hand[player][j] == (gold)) ) {
            TreasureCount++;
        }
    }
    if (TEXT_FEEDBACK) printf("Player %i TreasureHandCount count is: %i. Cards in deck: %i\n", player, TreasureCount, G->deckCount[player]);
    return TreasureCount;
}

int compareTreasureDeckCounts (struct gameState *Gpost, struct gameState *Gpre) {    //  make sure the copper count before and after card played is correct
    for (int i = 0; i < Gpost->numPlayers; i++) {
        int preTreasure =  getTreasureDeckCount(Gpre, i);
        if (preTreasure >= 2){                                                 // subtract 2 copper IF non-turn player has 2 or more copper in hand
            printf("**** POSSIBLE BUG >> if more than 2 treasure cards in deck, player should move 2 treasure cards from deck to hand. deckCount DOES decrement, but the prior values still in array. POSSIBLE bug depending upon interaction with other cards. \n");
            //assert (postTreasure == preTreasure + 2);                         // player should have 2 less copper after card played
            assert (Gpre->deckCount[G->whoseTurn] == Gpost->deckCount[G->whoseTurn] + 2);                    // indicates two cards removed from deck
            assert (Gpre->handCount[G->whoseTurn] + 2 == Gpost->handCount[G->whoseTurn]);                    // indicates two cards removed from deck
        }
        if (preTreasure < 2){
            printf("**** POSSIBLE BUG >> if more than 2 treasure cards in deck, player should move 2 treasure cards from deck to hand. deckCount DOES decrement, but the prior values still in array. POSSIBLE bug depending upon interaction with other cards. \n");
            //assert ( postTreasure == 0 );                                        // player should have ZERO copper after card played
        }
    }
    return 0;
}

int makeRandomHand (int player, int numCards) {
    for (int i = 0; i < numCards; i++){
        if (rand()%10 < 11) {                                                    // balance/skew the hand with some Treasure cards (set to all treasure currently)
            G->hand[player][i]=rand()% 3 + 4;                                    // cards 4, 5, and 6 are Copper Silver Gold
        }
        else G->hand[player][i]=rand()% NUM_UNIQUE_CARDS;
        G->handCount[player] = i;
    }
    return 0;
}

int makeRandomDeck (int player, int numCards) {
    for (int i = 0; i < numCards; i++){
        if (rand()%10 < 11) {                                                    // balance/skew the deck with some Treasure cards (set to all treasure currently)
            G->deck[player][i]=rand()% 3 + 4;                                    // cards 4, 5, and 6 are Copper Silver Gold
        }
        else G->deck[player][i]=rand()% NUM_UNIQUE_CARDS;                        // fills rest of deck with overall random (includes additional treasure)
        G->deckCount[player] = i;
    }
    
    return 0;
}

int compareCoins (struct gameState *Gpost, struct gameState *Gpre){
    assert (Gpost->coins = Gpre->coins + 2);   // two coins should be award for cutpurse card
    return 0;   // 0 if true
}

int compareNumActions ( struct gameState *Gpost, struct gameState *Gpre ){
    return ( Gpost->numActions - Gpre->numActions );
}

int getRandomKingdomCard (int kindomCardSet[]){
    int numCardsInSet = ((sizeof(*kindomCardSet) / (sizeof(int))));
    return rand()%numCardsInSet;
}

int getRandomTreasureCard (){
    int treasureCards[] = {copper, silver, gold};
    return treasureCards[rand()%3];
}

int main () {
    setUpRandomizerAdventurer();
    return 0;
}